# -*- coding: utf-8 -*-

import pygame
import sys
import os
import logging
import event
import time
from event_looper import EventLooper
from dispatcher import Dispatcher
from filter import *
from event_looper import *
from event_producer import *
import player
import background
from common import *
from pickle import UnpicklingError

SCREEN_RECT = pygame.rect.Rect(0,0,800, 600)
LOG_FILENAME = 'logs.txt'


def init():
    pygame.init()
    pygame.display.set_mode(SCREEN_RECT.size)
    player.init_player_sprite()
    background.init_background()
    
    logging.basicConfig(level = logging.WARNING)
    

def connect_server(sock, ip = '127.0.0.1', port = 1114, timeout = 5.0):
    '''
    z连接服务器的函数，连接成功返回(True,成功信息)，连接出错或者超时返回(False,错误信息)
    '''
    sock.connect(ip, port)
    startConnectTime = time.time()
    while True:
        time.sleep(1/100.0)
        
        sock.process()
        currentStats = sock.status()
        if currentStats == 2:
            return (True,u'连接成功')
        
        currentTime = time.time()
        if currentTime - startConnectTime >= timeout:
            return (False,u'超时')

import cPickle
def register(sock, name, role):
    '''
    向服务器发送注册请求，如果注册成功则返回(True,'成功信息')
    失败则返回(False,'失败信息')
    '''
    if sock.status() != 2:
        return (False, u'套接字未连接')
    
    time_out = 5.0
    start_time = time.time()
    
    reg_event = event.RegEvent(name, role)
    
    bytes = cPickle.dumps(reg_event, protocol=1)
    
    sock.send(bytes)
    
    while True:
        time.sleep(1/100.0)
        
        current_time = time.time()
        if current_time - start_time >= time_out:
            return (False,u'请求超时')
        
        sock.process()
        
        response = sock.recv()
        if response == '':
            continue
        
        try:
            confirm_event = cPickle.loads(response)
            if confirm_event.status == 0:
                return (True, u'注册成功')
            else:
                return (False, u'注册被拒绝')
        except UnpicklingError:
            return (False, u'反序列化确认信息失败')
    
    return (False, u'未知错误')

def login(sock, name):
    '''
    向服务器发送登录请求，如果登录成功则返回(True,player)，否则返回(False,错误信息)
    '''
    
    time_out = 5.0
    
    if sock.status() != 2:
        return (False,u'套接字未连接')
    
    start_time = time.time()
    
    login_event = event.LoginEvent(name)
    bytes = cPickle.dumps(login_event, protocol=1)
    
    sock.send(bytes)
    
    while True:
        time.sleep(1/100.0)
        
        current_time = time.time()
        if current_time - start_time >= time_out:
            return (False, u'请求超时')
        
        sock.process()
        
        response = sock.recv()
        if response == '':
            continue
        
        try:
            confirm_event = cPickle.loads(response)
            if confirm_event.status != 0:
                return (False, u'登录被拒绝')
            
            id = confirm_event.extra_data[D_ID]
            hp = confirm_event.extra_data[D_HP]
            pos = confirm_event.extra_data[D_POS]
            
            return (True, player.PlayerSprite(id, hp, pos))
            
        except UnpicklingError:
            return (False, u'反序列化确认信息失败')
        
def get_input_num(num_text):
    while True:
        for num in num_text:
            print '%d:%s' %(num, num_text[num])
        try:
            in_num = int( raw_input() )
        except:
            continue
        if in_num in num_text:
            break
    return in_num        

def reg_login(sock):
    while True:
        num_text = {
                1: u'注册用户',
                2: u'登陆用户'
                }
        choice = get_input_num(num_text)
    
        if choice == 1:
            name = raw_input(u'请输入要注册的用户名:')
            result,info = register(sock, name, 1)
            print info
                        
        elif choice == 2:
            name = raw_input(u'请输入要登录的用户名:')
            result,info = login(sock, name)
            if not result:
                print info
            else:
                print u'登录成功'
                return info
        
def main():

    init()
    
    server_ip = '127.0.0.1'
    
    sock = netstream.netstream()
    
    print '--------------------Start connect to the server---------------'
    while True:
        result, info = connect_server(sock, server_ip, PORT_NUM)
        if not result:
            print info
        else:
            break
    print '-------------------connectted to the server-------------------'
       
    my_player = reg_login(sock)
    
#    sock.connect(server_ip, PORT_NUM)
#    try_max_time = 6000
#    elapsed_time = 0
#    sleep_time = 1000 / 60
#    while True:
#        sock.process()
#        if sock.status() == 2:
#            break
#        pygame.time.wait(sleep_time)
#        elapsed_time += sleep_time
#        if elapsed_time > try_max_time:
#            break
#    if sock.status() != 2:
#        logging.info( 'Connect to server error!' )
#        sys.exit()
#
#    logging.info( 'Connectted to the server.' )
    
    all_group = pygame.sprite.LayeredUpdates()
    
#    PlayerSprite.groups.append(all_group)
#    Background.groups.append(all_group)
    
#    my_player = player.PlayerSprite(1, 100, (100,200))
    bg = background.get_background()
    
    all_group.add(bg, layer = 0)
    
    player.init_player_sprite_center(all_group)
    
    player_center = player.get_player_sprite_center()
    player_center.set_my_player(my_player)
    
    event_dispatcher = Dispatcher()
    
    quit_filter = QuitFilter()
    key_timestamp = TimeStampFilter()
    serial_filter = SerialFilter()
    print_filter = TestPrintFilter()
    send_filter = SendFilter(sock)
    
    client_update_filter = ClientUpdateFilter([all_group], all_group)
    receive_filter = ReceiveFilter(sock)
    deserial_filter = DeSerialFilter()
    client_handle_filter = ClientEventHandleFilter(player.get_player_sprite_center())
    try:
        event_dispatcher.attach(event.QuitEvent.event_id, quit_filter)
        
        event_dispatcher.attach(event.MoveEvent.event_id, send_filter)
#        event_dispatcher.attach(event.MoveEvent.event_id, print_filter)
        event_dispatcher.attach(event.MoveEvent.event_id, serial_filter)
        event_dispatcher.attach(event.MoveEvent.event_id, key_timestamp)
        
        event_dispatcher.attach(event.FrameEvent.event_id, client_handle_filter)
        event_dispatcher.attach(event.FrameEvent.event_id, print_filter)
        event_dispatcher.attach(event.FrameEvent.event_id, deserial_filter)
        event_dispatcher.attach(event.FrameEvent.event_id, receive_filter)
        event_dispatcher.attach(event.FrameEvent.event_id, client_update_filter)

    except Exception,data:
        logging.critical("Can't attach filter!Error msg:%s." % data)
        sys.exit()
    
    client_event_producer = EventProducer(ClientEventIt)
    e_looper = EventLooper(client_event_producer, event_dispatcher)
    e_looper.start()
    
if __name__ == '__main__':
    main()